package com.luyou.awt.canvas;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;

/**
 * 弹球游戏
 */
public class PinBall {

    private final int TABLE_WIDTH = 800;
    private final int TABLE_HEIGHT = 1000;

    //设置球拍参数
    private final int RACKET_Y = (int)(TABLE_HEIGHT * 0.9);
    private final int RACKET_WIDTH = 60;
    private final int RACKET_HEIGHT = 20;
    private final int RACKET_SPEED = 10;
    //球拍位置
    private int racketX = (TABLE_WIDTH - RACKET_WIDTH)/2;

    /**
     * 初始弹珠
     */
    private final int ballSize = 20;
    private java.util.List<MyBall> startBallList = new ArrayList<>();

    /**
     * 游戏中使用的弹珠
     */
    private java.util.List<MyBall> myBallList = new ArrayList<>();


    private Timer timer;

    private JFrame frame = new JFrame("弹球游戏");
    private SpringboardCanvas tableArea = new SpringboardCanvas();
    public void init(){
        tableArea.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT));
        frame.add(tableArea);
        KeyAdapter keyAdapter = new KeyAdapter(){
            @Override
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode() == KeyEvent.VK_LEFT){
                    if(racketX > 0){
                        racketX -= RACKET_SPEED;
                    }else{
                        racketX = 0;
                    }
                }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
                    if(racketX < TABLE_WIDTH - RACKET_WIDTH){
                        racketX += RACKET_SPEED;
                    }else {
                        racketX = TABLE_WIDTH - RACKET_WIDTH;
                    }
                }
                tableArea.repaint();
            }
        };
        frame.addKeyListener(keyAdapter);
        tableArea.addKeyListener(keyAdapter);
        //初始化一个球
        for (int i = 0; i < ballSize; i++) {
            MyBall myBall = new MyBall((TABLE_WIDTH - MyBall.BALL_SIZE) / 2, (int) (RACKET_Y * 0.2));
            startBallList.add(myBall);
        }
        double width = Toolkit.getDefaultToolkit().getScreenSize().getWidth();
        double height = Toolkit.getDefaultToolkit().getScreenSize().getHeight();
        timer = new Timer(100, e -> {
            for (MyBall ball : myBallList) {
                if(ball.hasDown){
                    ball.bally += ball.getBallSpeed();
                }else{
                    ball.bally -= ball.getBallSpeed();
                }
                if(ball.bally > TABLE_HEIGHT - MyBall.BALL_SIZE){
                    ball.hasDown = false;
                }else if(ball.bally < MyBall.BALL_SIZE){
                    ball.hasDown = true;
                }

                if(ball.direction == 0){
                   ball.ballX -= ball.getBallSpeed();
                }else{
                   ball.ballX += ball.getBallSpeed();
                }
                //碰到墙就退回
                if(ball.ballX < 0){
                   ball.ballX = 0;
                   ball.direction = 1;
                }else if(ball.ballX > TABLE_WIDTH - MyBall.BALL_SIZE){
                   ball.ballX = TABLE_WIDTH - MyBall.BALL_SIZE;
                   ball.direction = 0;
                }
                tableArea.repaint();
            }
        });
        timer.start();
        frame.setLocation((int)(width - TABLE_WIDTH)/2 , (int)(height - TABLE_HEIGHT)/2);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new PinBall().init();
    }


    /**
     * 碰撞检查
     */
    private void collisionInspection(){
        myBallList.removeIf(myBall ->
                racketX < myBall.ballX && myBall.ballX < (racketX + RACKET_WIDTH) && RACKET_Y - myBall.ballSize < myBall.bally);
    }

    /**
     * 跳板
     */
    class SpringboardCanvas extends Canvas{
        @Override
        public void paint(Graphics g) {
            if(startBallList.size()>0){
               MyBall myBall = startBallList.get(startBallList.size() - 1);
               startBallList.remove(startBallList.size() - 1);
               myBallList.add(myBall);
            }
            collisionInspection();
            //设置球的位置
            g.setColor(Color.orange);
            for (MyBall myBall : myBallList) {
                g.fillOval(myBall.ballX, myBall.bally, myBall.ballSize, myBall.ballSize);
            }

            //画挡板的位置
            g.setColor(new Color(80, 80, 200));
            g.fillRect(racketX, RACKET_Y, RACKET_WIDTH, RACKET_HEIGHT);
        }
    }

    static class MyBall{

        public static final int BALL_SIZE = 20;
        public static final int BALL_SPEED = 5;

        //球的大小
        private int ballSize;
        private int ballSpeed;
        private int ballX;
        private int bally;
        //方向 0向左 1向右
        private int direction;
        //方向 0向下 1向上
        private boolean hasDown ;

        public MyBall(int ballX, int bally) {
            this.ballX = ballX;
            this.bally = bally;
            direction = new Random().nextInt(2);
            ballSize = BALL_SIZE;
            ballSpeed = BALL_SPEED;
            hasDown = true;
        }

        public int getBallX() {
            return ballX;
        }

        public void setBallX(int ballX) {
            this.ballX = ballX;
        }

        public int getBally() {
            return bally;
        }

        public void setBally(int bally) {
            this.bally = bally;
        }

        public int getDirection() {
            return direction;
        }

        public void setDirection(int direction) {
            this.direction = direction;
        }

        public int getBallSize() {
            return ballSize;
        }

        public int getBallSpeed() {
            return ballSpeed;
        }

        public void setBallSize(int ballSize) {
            this.ballSize = ballSize;
        }

        public void setBallSpeed(int ballSpeed) {
            this.ballSpeed = ballSpeed;
        }

        public boolean isHasDown() {
            return hasDown;
        }

        public void setHasDown(boolean hasDown) {
            this.hasDown = hasDown;
        }
    }
}
